<script setup lang="ts">
import { Dialog, DialogDescription, DialogPanel, DialogTitle, TransitionChild, TransitionRoot } from '@headlessui/vue';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-vue';
import CarbonClose from '~icons/carbon/close';

const props = withDefaults(
  defineProps<{
    modelValue: boolean
    appear?: boolean
    side?: 'left' | 'right'
    title?: string
    preventClose?: boolean
    overlay?: boolean
  }>(),
  {
    modelValue: false,
    appear: false,
    side: 'right',
    preventClose: false,
    overlay: false,
  },
);

const emit = defineEmits<{
  'update:modelValue': [boolean]
  'close': []
}>();

const slots = useSlots();

const overlayTransitionClass = ref({
  enter: 'ease-in-out duration-500',
  enterFrom: 'opacity-0',
  enterTo: 'opacity-100',
  leave: 'ease-in-out duration-500',
  leaveFrom: 'opacity-100',
  leaveTo: 'opacity-0',
});

const transitionClass = computed(() => {
  return {
    enter: 'transform transition ease-in-out duration-300',
    leave: 'transform transition ease-in-out duration-200',
    enterFrom: props.side === 'left' ? '-translate-x-full' : 'translate-x-full',
    enterTo: 'translate-x-0',
    leaveFrom: 'translate-x-0',
    leaveTo: props.side === 'left' ? '-translate-x-full' : 'translate-x-full',
  };
});

const isOpen = computed({
  get() {
    return props.modelValue;
  },
  set(value) {
    emit('update:modelValue', value);
  },
});

function close() {
  isOpen.value = false;
  emit('close');
}
</script>

<template>
  <TransitionRoot as="template" :appear="appear" :show="isOpen">
    <Dialog class="fixed inset-0 z-1000 flex" :class="{ 'justify-end': side === 'right' }" @close="!preventClose && close()">
      <TransitionChild as="template" :appear="appear" v-bind="overlayTransitionClass">
        <div class="fixed inset-0 bg-stone-2/75 transition-opacity dark:bg-stone-8/75" :class="{ 'backdrop-blur-sm': overlay }" />
      </TransitionChild>
      <TransitionChild as="template" :appear="appear" v-bind="transitionClass">
        <DialogPanel
          relative
          max-w-md
          w-full
          w-screen
          flex
          flex-1
          flex-col
          bg-white
          dark:bg-stone-8
          focus:outline-none
        >
          <div
            flex="~ items-center justify-between"
            p-4
            border-b="~ solid stone/15"
            text-6
          >
            <DialogTitle
              m-0
              text-lg
              text-dark
              dark:text-white
            >
              {{ title }}
            </DialogTitle>
            <CarbonClose cursor-pointer @click="close" />
          </div>
          <DialogDescription m-0 flex-1 of-y-hidden>
            <OverlayScrollbarsComponent :options="{ scrollbars: { autoHide: 'leave', autoHideDelay: 300 } }" defer class="h-full p-4">
              <slot />
            </OverlayScrollbarsComponent>
          </DialogDescription>
          <div
            v-if="!!slots.footer"
            flex="~ items-center justify-end"
            px-3
            py-2
            border-t="~ solid stone/15"
          >
            <slot name="footer" />
          </div>
        </DialogPanel>
      </TransitionChild>
    </Dialog>
  </TransitionRoot>
</template>
